﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;

namespace SCRCPY
{

    public partial class SCRCPY : Form
    {
        const int PORT = 6789;
        string localFile = (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)) + "/1.jpeg";
        bool stop = false;
        int frameSize = 0;
        byte[] imagebuffer;
        Image image;
        Thread th;
        int SCREEN_W = 0;
        int SCREEN_H = 0;
        const int TX = 18;
        const int TY = 40;
        double dx = 1;
        double dy = 1;
        string file_;
        int w = 0;
        int h = 0;

        TcpListener listener_;

        //TcpClient tcpClient = new TcpClient();
        NetworkStream netStream_;
        TcpClient tcpClient_;
        volatile int fps = 0;
        volatile int transetSpeed = 0;
        public SCRCPY()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

            byte[] hapByte = Properties.Resources.entry_default_signed;
            string tempPath = (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)) + "/{C05EA035-B5F3-42B1-AB20-D275F12D895C}/";
            if (Directory.Exists(tempPath)) {
                Directory.Delete(tempPath,true);
            }
            Directory.CreateDirectory(tempPath);
            file_ = tempPath + "entry_default_signed.hap";
            File.WriteAllBytes(file_, hapByte);

            //ExecuteCmd("hdc.exe", "forward fport tcp:6789 tcp:6789");
            
            new Thread(() =>
            {
                ExecuteCmd("hdc.exe", "forward rport tcp:6789 tcp:6789");
                ExecuteCmd("hdc.exe", "install " + file_);
                ExecuteCmd("hdc.exe", "shell aa start -a EntryAbility -b com.ohos.scrcpy");
            }).Start();

        }
        private void SCRCPY_Load(object sender, EventArgs e)
        {

            th = new Thread(() =>
            {
                //Thread.Sleep(1000 * 2);
                //tcpClient.Connect("127.0.0.1", PORT);
                listener_ = new TcpListener(new IPEndPoint(IPAddress.Parse("127.0.0.1"), PORT));
                listener_.Start();


                tcpClient_ = listener_.AcceptTcpClient();//等待客户端连接

                netStream_ = tcpClient_.GetStream();
                while (!netStream_.CanRead && !netStream_.DataAvailable)
                {
                    Thread.Sleep(200);
                }

                while (!stop && tcpClient_.Connected)
                {
                    int size = RequestSize();
                    RequestFrame();
                    try
                    {
                        image = Image.FromStream(new MemoryStream(imagebuffer));

                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                    this.BeginInvoke(new Action(() =>
                    {
                        this.Invalidate();
                    }));
                    this.fps++;
                    Thread.Sleep(10);

                }
            });
            th.Start();
            this.timer.Start();
        }
        void WaitRead() {
            while (!netStream_.DataAvailable) {
                Thread.Sleep(30);
            }
        }

        int RequestSize() {

            //Console.WriteLine("netStream.WriteByte");
            netStream_.WriteByte(1);

            byte[] Sizebuffer = new byte[12];



            //Console.WriteLine("netStream.Read");
            WaitRead();
            int size = netStream_.Read(Sizebuffer, 0, 12);

            this.transetSpeed += size;

            w = System.BitConverter.ToInt32(Sizebuffer, 0);
            h = System.BitConverter.ToInt32(Sizebuffer, 4);
            this.frameSize = System.BitConverter.ToInt32(Sizebuffer, 8);
            this.imagebuffer = new byte[this.frameSize];
            Console.WriteLine("frame info:" + w + "," + h + "," + frameSize);
            return this.frameSize;
        }

        void RequestFrame() {
            //Console.WriteLine("netStream.WriteByte 2");
            netStream_.WriteByte(2);
            //Console.WriteLine("netStream.Read 2");
            int slice = 1024;
            int count = 0;
            while (count < this.frameSize)
            {
                int nSize = 0;
                if (this.frameSize - count <= slice)
                {
                    nSize = this.frameSize - count;
                }
                else
                {
                    nSize = slice;
                }


                int readSize = netStream_.Read(imagebuffer, count, nSize);
                count = count + readSize;
                this.transetSpeed += readSize;
            }
            
        }       

        private void SCRCPY_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.stop = true;
            this.th.Abort();
        }

        private void SCRCPY_Paint(object sender, PaintEventArgs e)
        {
            if (image != null)
            {
                SCREEN_W = image.Width;
                SCREEN_H = image.Height;
                this.Width = SCREEN_W / 2 + TX;
                this.Height = SCREEN_H / 2 + TY;

                dx = 1.0 * SCREEN_W / (this.Width - TX);
                dy = 1.0 * SCREEN_H / (this.Height - TY);
                //this.MaximumSize = new Size(this.Width, this.Height);


                Point p = new Point(0, 0);
                e.Graphics.ScaleTransform(0.5f, 0.5f);
                e.Graphics.DrawImage(image, p);
            }
        }

        static void ExecuteCmd(string exefile, string arguments) 
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            processStartInfo.UseShellExecute = false;
            processStartInfo.RedirectStandardOutput = true;
            processStartInfo.Arguments = arguments;
            processStartInfo.FileName = exefile;
            processStartInfo.CreateNoWindow = true;
            Process p = new Process();
            p.StartInfo = processStartInfo;
            p.Start();
            p.WaitForExit();
            Console.WriteLine(p.StandardOutput.ReadToEnd());

        }

        private void SCRCPY_MouseUp(object sender, MouseEventArgs e)
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            long mouseUp = Convert.ToInt64(ts.TotalMilliseconds);

            int x = (int)(1.0 * e.X * (dx));
            int y = (int)(1.0 * e.Y * (dy));
            string cmd;
            long time = mouseUp - mouseDown;
            if (time <= 100)
            {
                time = 100;
                cmd = "shell uinput -T -c " + x + " " + y + " " + time;
            }
            else
            {
                cmd = "shell uinput -T -m " + downX + " " + downY + " " + x + " " + y + " " + time;
            }

            //double x = 100;
            //double y = 200;
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            processStartInfo.UseShellExecute = false;
            processStartInfo.RedirectStandardOutput = true;
            processStartInfo.Arguments = cmd;
            processStartInfo.FileName = "hdc.exe";
            processStartInfo.CreateNoWindow = true;
            Process p = new Process();
            p.StartInfo = processStartInfo;
            p.Start();
            //p.WaitForExit();
            //string s = p.StandardOutput.ReadToEnd();
            //Console.WriteLine(s);
        }

        long mouseDown = 0;
        int downX = 0;
        int downY = 0;
        private void SCRCPY_MouseDown(object sender, MouseEventArgs e)
        {
            TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            mouseDown = Convert.ToInt64(ts.TotalMilliseconds);

            downX = (int)(1.0 * e.X * (dx));
            downY = (int)(1.0 * e.Y * (dy));
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            double rate = this.transetSpeed / 1024.0;
            this.Text ="SCRCPY fps：" + this.fps.ToString() + " rate："+ rate.ToString("F1") + "KB/s";
            this.fps = 0;
            this.transetSpeed = 0;
        }
    }
}
